package com.itany.nmms.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itany.nmms.constant.DictConstant;
import com.itany.nmms.constant.StatusConstant;
import com.itany.nmms.dao.DeptMapper;
import com.itany.nmms.dao.SequenceMapper;
import com.itany.nmms.entity.*;
import com.itany.nmms.exception.DeptExistException;
import com.itany.nmms.exception.DeptStatusException;
import com.itany.nmms.exception.LoginDisabledException;
import com.itany.nmms.exception.RequestParameterErrorException;
import com.itany.nmms.factory.ObjectFactory;
import com.itany.nmms.service.DeptService;
import com.itany.nmms.util.ParameterUtil;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author 石小俊
 * @date 2024年05月15日 18:20
 */
public class DeptServiceImpl implements DeptService {
    @Override
    public void addFatherDept(String name, String remark, Staff staff) throws LoginDisabledException, RequestParameterErrorException, DeptExistException {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        SequenceMapper sequenceMapper = (SequenceMapper) ObjectFactory.getObject("sequenceMapper");
        if (staff == null) {
            throw new LoginDisabledException("登录失效,请重新登录");
        }
        if (ParameterUtil.isNull(name) || ParameterUtil.isNull(remark)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        // 部门名称不能重复
        DeptExample example = new DeptExample();
        example.or()
                .andDeptNameEqualTo(name);
        List<Dept> depts = deptMapper.selectByExample(example);
        if (!depts.isEmpty()) {
            throw new DeptExistException("该部门已经存在");
        }

        // 准备添加
        Dept dept = new Dept();
        dept.setDeptName(name);
        dept.setRemark(remark);
        // 默认设置为有效状态
        dept.setIsValid(StatusConstant.DEPT_IS_VALID_YES);
        dept.setCreateDate(new Date());
        dept.setCreateStaffId(staff.getStaffId());

        // 生成部门编号
        SequenceExample sequenceExample = new SequenceExample();
        sequenceExample.or()
                .andNameEqualTo(DictConstant.DEPT_NO_PREFIX);
        List<Sequence> sequences = sequenceMapper.selectByExample(sequenceExample);
        if (sequences.isEmpty()) {
            // 创建初始数据
            Sequence sequence = new Sequence();
            sequence.setName(DictConstant.DEPT_NO_PREFIX);
            sequence.setValue(DictConstant.DEPT_NO_INIT_VALUE);
            // 将数据存储到序列号表中
            sequenceMapper.insertSelective(sequence);
            // 生成此时对应的部门编号
            dept.setDeptNo(DictConstant.DEPT_NO_PREFIX + new SimpleDateFormat("yyyyMMdd").format(new Date()) + sequence.getValue());
        } else {
            // 取出当前已有的序列号数据
            Sequence sequence = sequences.get(0);
            // 判断序列号的值是否达到了最大值
            if (DictConstant.DEPT_NO_MAX_VALUE.equals(sequence.getValue())) {
                // 如果达到了最大值,则下一个值为初始值
                sequence.setValue(DictConstant.DEPT_NO_INIT_VALUE);
            } else {
                // 否则在原有值的基础上+1
                sequence.setValue(ParameterUtil.nextValue(sequence.getValue()));
            }
            // 执行修改操作
            sequenceMapper.updateByPrimaryKeySelective(sequence);
            // 生成此时对应的部门编号
            dept.setDeptNo(DictConstant.DEPT_NO_PREFIX + new SimpleDateFormat("yyyyMMdd").format(new Date()) + sequence.getValue());
        }
        deptMapper.insertSelective(dept);
    }

    @Override
    public void addSonDept(String fatherId, String name, String remark, Staff staff) throws LoginDisabledException, RequestParameterErrorException, DeptExistException {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        SequenceMapper sequenceMapper = (SequenceMapper) ObjectFactory.getObject("sequenceMapper");
        if (staff == null) {
            throw new LoginDisabledException("登录失效,请重新登录");
        }
        if (ParameterUtil.isNull(fatherId) || ParameterUtil.isNull(name) || ParameterUtil.isNull(remark)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        // 部门名称不能重复
        DeptExample example = new DeptExample();
        example.or()
                .andDeptNameEqualTo(name);
        List<Dept> depts = deptMapper.selectByExample(example);
        if (!depts.isEmpty()) {
            throw new DeptExistException("该部门已经存在");
        }

        // 准备添加
        Dept dept = new Dept();
        dept.setDeptName(name);
        dept.setRemark(remark);
        // 默认设置为有效状态
        dept.setIsValid(StatusConstant.DEPT_IS_VALID_YES);
        dept.setCreateDate(new Date());
        dept.setCreateStaffId(staff.getStaffId());
        // 设置上级部门编号
        dept.setFatherDeptId(Integer.parseInt(fatherId));

        // 生成部门编号
        SequenceExample sequenceExample = new SequenceExample();
        sequenceExample.or()
                .andNameEqualTo(DictConstant.DEPT_NO_PREFIX);
        List<Sequence> sequences = sequenceMapper.selectByExample(sequenceExample);
        if (sequences.isEmpty()) {
            // 创建初始数据
            Sequence sequence = new Sequence();
            sequence.setName(DictConstant.DEPT_NO_PREFIX);
            sequence.setValue(DictConstant.DEPT_NO_INIT_VALUE);
            // 将数据存储到序列号表中
            sequenceMapper.insertSelective(sequence);
            // 生成此时对应的部门编号
            dept.setDeptNo(DictConstant.DEPT_NO_PREFIX + new SimpleDateFormat("yyyyMMdd").format(new Date()) + sequence.getValue());
        } else {
            // 取出当前已有的序列号数据
            Sequence sequence = sequences.get(0);
            // 判断序列号的值是否达到了最大值
            if (DictConstant.DEPT_NO_MAX_VALUE.equals(sequence.getValue())) {
                // 如果达到了最大值,则下一个值为初始值
                sequence.setValue(DictConstant.DEPT_NO_INIT_VALUE);
            } else {
                // 否则在原有值的基础上+1
                sequence.setValue(ParameterUtil.nextValue(sequence.getValue()));
            }
            // 执行修改操作
            sequenceMapper.updateByPrimaryKeySelective(sequence);
            // 生成此时对应的部门编号
            dept.setDeptNo(DictConstant.DEPT_NO_PREFIX + new SimpleDateFormat("yyyyMMdd").format(new Date()) + sequence.getValue());
        }
        deptMapper.insertSelective(dept);
    }

    @Override
    public PageInfo<Dept> findPage(String pageNo, String pageSize) {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        if (ParameterUtil.isNull(pageNo)) {
            pageNo = DictConstant.DEPT_DEFAULT_PAGE_NO;
        }
        if (ParameterUtil.isNull(pageSize)) {
            pageSize = DictConstant.DEPT_DEFAULT_PAGE_SIZE;
        }
        PageHelper.startPage(Integer.parseInt(pageNo), Integer.parseInt(pageSize));

        List<Dept> depts = deptMapper.selectAll();

        PageInfo<Dept> deptPage = new PageInfo<>(depts);
        return deptPage;
    }

    @Override
    public Dept findById(String id) throws RequestParameterErrorException {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        if (ParameterUtil.isNull(id)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        Dept dept = deptMapper.selectByPrimaryKey(Integer.parseInt(id));
        return dept;
    }

    @Override
    public void modifyDept(String id, String name, String remark) throws RequestParameterErrorException, DeptExistException {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        if (ParameterUtil.isNull(id) || ParameterUtil.isNull(name) || ParameterUtil.isNull(remark)) {
            throw new RequestParameterErrorException("请求参数有误");
        }

        // 部门名不能重复,但是可以是当前的
        DeptExample example = new DeptExample();
        example.or()
                .andDeptNameEqualTo(name)
                .andDeptIdNotEqualTo(Integer.parseInt(id));
        List<Dept> depts = deptMapper.selectByExample(example);
        if (!depts.isEmpty()) {
            throw new DeptExistException("该部门已经存在");
        }

        Dept dept = new Dept();
        dept.setDeptId(Integer.parseInt(id));
        dept.setDeptName(name);
        dept.setRemark(remark);

        deptMapper.updateByPrimaryKeySelective(dept);
    }

    @Override
    public void enableDept(String id) throws RequestParameterErrorException, DeptStatusException {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        if (ParameterUtil.isNull(id)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        // 启用时需要判断上级部门的状态
        // 查询当前部门信息
        Dept dept = deptMapper.selectByPrimaryKey(Integer.parseInt(id));
        // 查询上级部门信息
        Dept fatherDept = deptMapper.selectByPrimaryKey(dept.getFatherDeptId());
        // 当存在上级部门且上级部门状态为禁用时,无法启用,抛出异常
        if (fatherDept != null && StatusConstant.DEPT_IS_VALID_NO == fatherDept.getIsValid()) {
            throw new DeptStatusException("请先启用上级部门");
        }
        // 启用当前部门
        dept.setIsValid(StatusConstant.DEPT_IS_VALID_YES);
        deptMapper.updateByPrimaryKeySelective(dept);
    }

    @Override
    public void disableDept(String id) throws RequestParameterErrorException {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        if (ParameterUtil.isNull(id)) {
            throw new RequestParameterErrorException("请求参数有误");
        }
        // 查询当前部门信息
        Dept dept = deptMapper.selectByPrimaryKey(Integer.parseInt(id));
        // 禁用当前部门
        dept.setIsValid(StatusConstant.DEPT_IS_VALID_NO);
        deptMapper.updateByPrimaryKeySelective(dept);

        // 查询当前部门下的所有子部门
        DeptExample example = new DeptExample();
        example.or()
                .andFatherDeptIdEqualTo(dept.getDeptId());
        List<Dept> sonDepts = deptMapper.selectByExample(example);
        // 递归操作
        for (Dept sonDept : sonDepts) {
            disableDept(sonDept.getDeptId().toString());
        }
    }

    @Override
    public List<Dept> findAll() {
        DeptMapper deptMapper = (DeptMapper) ObjectFactory.getObject("deptMapper");
        List<Dept> depts = deptMapper.selectByExample(new DeptExample());
        return depts;
    }
}
